/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation
 ******************************************************************************/
package net.sourceforge.perforce.internal.api;

import junit.framework.TestCase;

import net.sourceforge.perforce.api.IClientUserDelegate;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

/**
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 * @version $Revision: 488 $
 */
abstract class ClientUserTestCase extends TestCase {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the digester to read the ClientUser scripts. */
  private Digester digester;

  // -------------------------------------------------------------------------
  // Public Constructors

  /**
   * Constructor for ClientUserTestCase.
   * 
   * @param name the name of the test case.
   */
  ClientUserTestCase(String name) {
    super(name);
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Loads the given script and executes it on the specified client user.
   * 
   * @param is input stream containing the script.
   * @param clientUser the Client User.
   * @throws IOException in case of an I/O error.
   * @throws SAXException in case of an invalid script file.
   */
  @SuppressWarnings("unchecked")
  // commandList
  public void executeScript(InputStream is, IClientUserDelegate clientUser) throws IOException,
      SAXException {
    digester.push(new LinkedList());
    List<ICommand> commandList = (List<ICommand>) digester.parse(is);

    for (ICommand command : commandList) {
      command.execute(clientUser);
    }
    clientUser.finished();
  }

  // ---------------------------------------------------------------------------
  // Protected Methods

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    digester = new Digester();

    // outputError
    digester.addObjectCreate("ClientUserScript/outputError", OutputErrorCommand.class);
    digester.addSetProperties("ClientUserScript/outputError");
    digester.addSetNext("ClientUserScript/outputError", "add");

    // outputInfo
    digester.addObjectCreate("ClientUserScript/outputInfo", OutputInfoCommand.class);
    digester.addSetProperties("ClientUserScript/outputInfo");
    digester.addSetNext("ClientUserScript/outputInfo", "add");
  }


  // -----------------------------------------------------------------------
  // Public Nested Classes

  /** Interface defining the methods of the commands. */
  public static interface ICommand {
    //--------------------------------------------------------------------------
    // ------- Methods

    /**
     * Called to execute the command.
     * 
     * @param clientUser the IClientUserDelegate on which the command is
     *        performed.
     */
    void execute(IClientUserDelegate clientUser);
  }

  /** Command that performs IClientUserDelegate.outputError calls. */
  public static class OutputErrorCommand implements ICommand {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores the errorString. */
    private String errorString;

    //--------------------------------------------------------------------------
    // Public Methods

    /**
     * Sets the error string.
     * 
     * @param theErrorString the error string to set.
     */
    public void setErrorString(String theErrorString) {
      errorString = theErrorString;
    }

    public void execute(IClientUserDelegate clientUser) {
      clientUser.outputError(errorString);
    }

    @Override
    public String toString() {
      return "outputError: " + errorString;
    }
  }

  /** Command that performs IClientUserDelegate.outputInfo calls. */
  public static class OutputInfoCommand implements ICommand {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores the info level. */
    private char infoLevel;
    /** Stores the infoString. */
    private String infoString;

    //--------------------------------------------------------------------------
    // Public Methods

    /**
     * Sets the info level.
     * 
     * @param theInfoLevel the info level to set.
     */
    public void setLevel(char theInfoLevel) {
      infoLevel = theInfoLevel;
    }

    /**
     * Sets the info string.
     * 
     * @param theInfoString the info string to set.
     */
    public void setInfoString(String theInfoString) {
      infoString = theInfoString;
    }

    public void execute(IClientUserDelegate clientUser) {
      clientUser.outputInfo(infoLevel, infoString);
    }

    @Override
    public String toString() {
      return "outputInfo: " + infoLevel + " " + infoString;
    }
  }
}
